package com.ruolin.micro.gateway.server.route;

import cn.hutool.core.lang.Assert;
import com.ruolin.micro.gateway.server.cache.ApplicationRouterMetadataCache;
import com.ruolin.micro.gateway.server.constant.RouterConstant;
import com.ruolin.micro.gateway.server.servlet.bean.RouterBeanDefinition;
import com.ruolin.micro.gateway.server.metadata.ApplicationRouteMetadata;
import com.ruolin.micro.gateway.server.metadata.MethodRouteMetadata;

import java.text.MessageFormat;
import java.util.List;
import java.util.Optional;

public class DefaultApplicationRouteLocator implements ApplicationRouteLocator {

    @Override
    public MethodRouteMetadata getMethodRouteMetadata(String requestRoute, List<RouterBeanDefinition> routerBeanDefinitions) {
        RouterBeanDefinition routerBeanDefinition = getRouterBeanDefinition(requestRoute, routerBeanDefinitions);

        String uri = routerBeanDefinition.getUri();
        Assert.notEmpty(uri);

        String application = uri.substring(RouterConstant.SYMBOL.length());
        ApplicationRouteMetadata applicationRouteMetadata = ApplicationRouterMetadataCache.getMetadataCache().getIfPresent(application);
        String routePart = requestRoute.substring(routerBeanDefinition.getPath().length());

        Optional<MethodRouteMetadata> methodRouteMetadataOptional = applicationRouteMetadata.getMethods()
                .stream()
                .filter(a -> routePart.equals(a.getRoutePart()) || a.match(routePart))
                .findFirst();

        return methodRouteMetadataOptional.orElseThrow(() ->
                new IllegalArgumentException(MessageFormat.format("route::::[routePart ->{0},application::{1}->method does not match", routePart, application)));

    }

    @Override
    public ApplicationRouteMetadata getApplicationRouteMetadata(String requestRoute, List<RouterBeanDefinition> routerBeanDefinitions) {
        RouterBeanDefinition routerBeanDefinition = getRouterBeanDefinition(requestRoute, routerBeanDefinitions);

        String uri = routerBeanDefinition.getUri();
        Assert.notEmpty(uri);

        String application = uri.substring(RouterConstant.SYMBOL.length());
        return ApplicationRouterMetadataCache.getMetadataCache().getIfPresent(application);
    }

    protected RouterBeanDefinition getRouterBeanDefinition(String requestRoute, List<RouterBeanDefinition> routerBeanDefinitions){
        Optional<RouterBeanDefinition> routerOptional = routerBeanDefinitions.stream().filter(r -> requestRoute.startsWith(r.getPath())).findFirst();
       return routerOptional.orElseThrow(() ->
                new IllegalArgumentException(MessageFormat.format("[route->{0},does not match]", requestRoute)));
    }
}
